#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <json-c/json.h>
// Requer libcurl e libjson-c


struct dadosJSON {
  char *conteudo;
  size_t tamanho;
};


static size_t callbackEscrita(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t tamanhoReal = size * nmemb;
    struct dadosJSON *dj = (struct dadosJSON *) userp;

    dj->conteudo = realloc(dj->conteudo, dj->tamanho + tamanhoReal + 1);
    if (dj->conteudo == NULL) {
        printf("realloc() retornou NULL, isso significa que não temos mais memória em\n");
        return 0;
    }

    memcpy(&(dj->conteudo[dj->tamanho]), contents, tamanhoReal);
    dj->tamanho += tamanhoReal;
    dj->conteudo[dj->tamanho] = 0;

    return tamanhoReal;
}


json_object* puxaDetalhes(char* id) {
    CURL *curl;
    char *resposta;
    struct dadosJSON dj;

    curl = curl_easy_init();

    char url[50] = "https://nhentai.net/api/gallery/";
    strcat(url, id);

    dj.conteudo = malloc(1);
    dj.tamanho = 0;
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callbackEscrita);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &dj);

        CURLcode status = curl_easy_perform(curl);
        json_object *jobj = json_tokener_parse(dj.conteudo);
        if (dj.conteudo)
            free(dj.conteudo);

        if (status == CURLE_OK) {
            curl_easy_cleanup(curl);
            return jobj;
        }
    }
}

char* verificaFormato(char urlBase[15], int media_id, char filename[10], int pagina) {
    CURL *curl;
    curl = curl_easy_init();

    char url[50] = "https://i.nhentai.net/galleries/";
    char m_id[15];
    char c_pagina[3];
    sprintf(m_id, "%i", media_id);
    strcat(url, m_id);
    strcat(url, "/");
    sprintf(c_pagina, "%i", pagina);
    strcat(url, c_pagina);
    strcat(url, ".jpg");


    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
        curl_easy_setopt(curl, CURLOPT_NOBODY, 1);

        CURLcode status = curl_easy_perform(curl);
        if (status == CURLE_OK && strstr(url, ".jpg")) {
            return ".jpg";
        } else {
            return ".png";
        }
        curl_easy_cleanup(curl);
    }
}

void efetuaDownloads(int media_id, int paginas, char* id) {
    CURL *curl;
    curl = curl_easy_init();
    for (int pagina = 1; pagina <= paginas; pagina++) {
        FILE *arquivo;
        char filename[8];
        char formato[5];
        strcpy(formato, verificaFormato("https://i.nhentai.net/galleries/", media_id, filename, pagina));
        sprintf(filename, "%i", pagina);

        char localFilename[14];
        strcpy(localFilename, id);
        strcat(localFilename, "_");
        strcat(localFilename, filename);
        strcat(localFilename, formato);

        strcat(filename, formato);

        char url[50] = "https://i.nhentai.net/galleries/";
        char m_id[15];
        sprintf(m_id, "%i", media_id);
        strcat(url, m_id);
        strcat(url, "/");
        strcat(url, filename);


        arquivo = fopen(localFilename, "wb");

        if (curl) {
            printf("Baixando arquivo %i de %i (%s)\n", pagina, paginas, url);

            curl_easy_setopt(curl, CURLOPT_URL, url);
            curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, arquivo);

            CURLcode resposta = curl_easy_perform(curl);
            if (resposta == CURLE_OK) {
                printf("Página %i baixada com sucesso em %s!\n\n", pagina, localFilename);
            } else {
                printf("Erro ao baixar a página %i (DEBUG: %s)\n\n", pagina, curl_easy_strerror(resposta));
            }

            fclose(arquivo);
            curl_easy_cleanup(curl);
        }
    }
}

int main(int argc, char *argv[]) {
    char *id = argv[1];
    char *paginas = argv[2];

    int media_id = atoi(json_object_get_string(json_object_object_get(puxaDetalhes(id), "media_id")));
    int num_pages = atoi(json_object_get_string(json_object_object_get(puxaDetalhes(id), "num_pages")));

    num_pages = paginas ? atoi(paginas) : num_pages;

    efetuaDownloads(media_id, num_pages, id);
}